package oplog

import (
	"context"
	"devops-super/api"
	v1 "devops-super/api/syslog/v1"
	"devops-super/internal/dao"
	"devops-super/internal/model/entity"
	"devops-super/internal/model/mymodel"
	"devops-super/internal/service"
	"github.com/gogf/gf/v2/errors/gcode"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/os/grpool"
	"github.com/gogf/gf/v2/os/gtime"
	"time"
)

type sOplog struct {
	Pool *grpool.Pool
}

var cols = dao.SysOperLog.Columns()

func init() {
	service.RegisterOplog(New())
}

func New() *sOplog {
	return &sOplog{
		Pool: grpool.New(100),
	}
}

// Add 添加操作日志
func (*sOplog) Add(ctx context.Context, in *mymodel.OperLog) (err error) {
	// 创建实体对象并设置字段
	oplogEntity := &entity.SysOperLog{
		Title:         in.Title,
		BusinessType:  in.BusinessType,
		Method:        in.Method,
		RequestMethod: in.RequestMethod,
		OperatorType:  in.OperatorType,
		OperName:      in.OperName,
		DeptId:        in.DeptId,
		OperUrl:       in.OperUrl,
		OperIp:        in.OperIp,
		OperLocation:  in.OperLocation,
		OperParam:     in.OperParam,
		ErrorMsg:      in.ErrorMsg,
		OperTime:      gtime.Now(),
	}

	// 插入数据
	_, err = dao.SysOperLog.Ctx(ctx).Insert(oplogEntity)
	return
}

// Del 删除操作日志
func (*sOplog) Del(ctx context.Context, operId uint64) (err error) {
	_, err = dao.SysOperLog.Ctx(ctx).WherePri(operId).Delete()
	return
}

// BatchDel 批量删除操作日志
func (*sOplog) BatchDel(ctx context.Context, operIds []uint64) (err error) {
	if len(operIds) > 0 {
		_, err = dao.SysOperLog.Ctx(ctx).WhereIn(dao.SysOperLog.Columns().OperId, operIds).Delete()
	}
	return
}

// GetPageLst 分页获取操作日志列表
func (*sOplog) GetPageLst(ctx context.Context, req *v1.GetPageLstReq) (res *v1.GetPageLstRes, err error) {
	// 初始化响应对象
	res = &v1.GetPageLstRes{}
	pageRes := &api.PageLstRes[*mymodel.OperLogResponse]{}
	m := dao.SysOperLog.Ctx(ctx).Safe(true)

	// 按操作URL筛选
	if req.OperUrl != "" {
		m = m.Where(cols.OperUrl+" like ?", "%"+req.OperUrl+"%")
	}

	// 按部门ID筛选
	if req.DeptId > 0 {
		m = m.Where(cols.DeptId, req.DeptId)
	}
	isSuperDept, currentUser, _ := service.User().IsCurrentUserSuperDept(ctx)
	if !isSuperDept {
		m = m.Where(cols.DeptId, currentUser.DeptId)
	}

	// 按时间范围筛选
	if req.TimeRange != nil {
		if len(req.TimeRange) != 2 {
			return nil, gerror.NewCode(gcode.CodeInvalidParameter, "时间范围参数格式错误")
		}
		// 新增时间转换逻辑
		startTime, err := time.Parse(time.RFC3339, req.TimeRange[0])
		if err != nil {
			return nil, gerror.WrapCode(gcode.CodeInvalidParameter, err, "开始时间格式错误")
		}
		endTime, err := time.Parse(time.RFC3339, req.TimeRange[1])
		if err != nil {
			return nil, gerror.WrapCode(gcode.CodeInvalidParameter, err, "结束时间格式错误")
		}
		timeLayout := "2006-01-02 15:04:05"
		timeStr0 := startTime.Local().Format(timeLayout)
		timeStr1 := endTime.Local().Format(timeLayout)
		m = m.WhereBetween(cols.OperTime, timeStr0, timeStr1)
	}

	// 处理通用的查询条件（从PageLstReq继承的Wheres字段）
	if req.Wheres != nil {
		// 按业务类型筛选
		if businessType := req.Wheres.Get("businessType"); !businessType.IsNil() {
			m = m.Where(cols.BusinessType, businessType.Int())
		}

		// 按操作类型筛选
		if operatorType := req.Wheres.Get("operatorType"); !operatorType.IsNil() {
			m = m.Where(cols.OperatorType, operatorType.Int())
		}

		// 按操作人员筛选
		if operName := req.Wheres.Get("operName"); !operName.IsNil() {
			m = m.Where(cols.OperName+" like ?", "%"+operName.String()+"%")
		}

		// 按模块标题筛选
		if title := req.Wheres.Get("title"); !title.IsNil() {
			m = m.Where(cols.Title+" like ?", "%"+title.String()+"%")
		}

		// 按操作IP筛选
		if operIp := req.Wheres.Get("operIp"); !operIp.IsNil() {
			m = m.Where(cols.OperIp+" like ?", "%"+operIp.String()+"%")
		}
	}

	// 默认按操作时间降序排序
	m = m.OrderDesc(cols.OperTime)

	// 分页查询原始实体
	var entities []*entity.SysOperLog
	if err = m.Offset(req.Offset()).Limit(req.Limit()).ScanAndCount(&entities, &pageRes.Total, false); err != nil {
		return res, err
	}

	// 转换为响应模型
	pageRes.List = make([]*mymodel.OperLogResponse, len(entities))
	for i, e := range entities {
		pageRes.List[i] = &mymodel.OperLogResponse{
			OperId:        e.OperId,
			Title:         e.Title,
			BusinessType:  e.BusinessType,
			Method:        e.Method,
			RequestMethod: e.RequestMethod,
			OperatorType:  e.OperatorType,
			OperName:      e.OperName,
			DeptId:        e.DeptId,
			OperUrl:       e.OperUrl,
			OperIp:        e.OperIp,
			OperLocation:  e.OperLocation,
			OperParam:     e.OperParam,
			ErrorMsg:      e.ErrorMsg,
			OperTime:      e.OperTime,
		}
	}

	// 设置响应数据
	res.PageLstRes = pageRes
	return res, nil
}

// GetOne 获取单条操作日志
func (*sOplog) GetOne(ctx context.Context, operId uint64) (out *entity.SysOperLog, err error) {
	out = &entity.SysOperLog{}
	err = dao.SysOperLog.Ctx(ctx).WherePri(operId).Scan(out)
	return
}
